package cn.tedu.orderservice.config;

import cn.tedu.charging.common.pojo.vo.ChargingProcessVO;
import cn.tedu.charging.common.response.JsonResult;
import cn.tedu.charging.common.response.StatusCode;
import cn.tedu.charging.common.util.JsonUtil;
import cn.tedu.orderservice.constant.Constant;
import cn.tedu.orderservice.constant.MqttTopicConstant;
import cn.tedu.charging.common.pojo.dto.ChargingProcessDTO;
import cn.tedu.orderservice.feign.CostClient;
import cn.tedu.orderservice.feign.UserClient;
import cn.tedu.orderservice.pojo.dto.DeviceChargingDTO;
import cn.tedu.orderservice.pojo.po.ChargingProcessPO;
import cn.tedu.orderservice.repository.ChargingProcessRepository;
import cn.tedu.orderservice.repository.OrderRepository;
import cn.tedu.orderservice.websocket.WebSocketServer;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.awt.*;
import java.math.BigDecimal;

@Slf4j
@Configuration
public class MqttClientConfiguration {
    @Value("${mqtt.username}")
    private String username;
    @Value("${mqtt.password}")
    private String password;
    @Value("${mqtt.host}")
    private String host;
    @Value("${mqtt.clientId}")
    private String clientId;

    @Autowired
    private OrderRepository orderRepository;
    @Autowired
    private CostClient costClient;
    @Autowired
    private UserClient userClient;
    @Autowired
    private ChargingProcessRepository chargingProcessRepository;

    @Bean
    public MqttClient getMqttClient() throws MqttException {
        //创建客户端对象
        MqttClient mqttClient=new MqttClient(host,clientId);
        //创建连接对象参数
        MqttConnectOptions mqttConnectOptions=new MqttConnectOptions();
        mqttConnectOptions.setUserName(username);
        mqttConnectOptions.setPassword(password.toCharArray());
        //设置配置参数
        mqttConnectOptions.setAutomaticReconnect(true);
        mqttConnectOptions.setCleanSession(true);
        mqttConnectOptions.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1_1);
        //设置返回消息接收
        mqttClient.setCallback(new MqttCallbackExtended() {
            //连接成功
            @Override
            public void connectComplete(boolean b, String s) {
                log.debug("连接成功------------"+b+s);
                try {
                    //接收到开始充电指令,充电桩返回消息
                    mqttClient.subscribe(MqttTopicConstant.TOPIC_CHARGING_RESULT,0);
                    //充电桩同步消息
                    mqttClient.subscribe(MqttTopicConstant.TOPIC_CHARGING_PROCESS,0);
                } catch (MqttException e) {
                    e.printStackTrace();
                }
            }
            //连接失败
            @Override
            public void connectionLost(Throwable throwable) {
                log.debug("连接失败--------------");
            }

            //接收消息执行
            @Override
            public void messageArrived(String s, MqttMessage mqttMessage) throws Exception {
                if (MqttTopicConstant.TOPIC_CHARGING_RESULT.equals(s)){
                    log.debug("接收充电数据:topic:{},message:{}", s,mqttMessage);
                    DeviceChargingDTO deviceChargingDTO = JsonUtil.fromJson(mqttMessage.toString(), DeviceChargingDTO.class);
                    log.debug("转化对象成功");
                    if (deviceChargingDTO != null) {
                        String result = deviceChargingDTO.getResult();
                        if (Constant.RESULT_START_CHARGING_SUCCESS.equals(result)) {
                            log.debug("充电桩开始充电-创建订单-传入参数:{}",deviceChargingDTO);
                            //创建订单成功记录
                            orderRepository.saveSuccessful(deviceChargingDTO);
                        } else {
                            log.debug("充电桩故障");
                            //创建订单失败记录
                            orderRepository.saveFailed(deviceChargingDTO);
                        }
                    }

                }else if (MqttTopicConstant.TOPIC_CHARGING_PROCESS.equals(s)){
                    log.debug("接收同步状态数据:topic:{},message:{}", s,mqttMessage);
                    ChargingProcessDTO chargingProcessDTO = JsonUtil.fromJson(mqttMessage.toString(), ChargingProcessDTO.class);
                    log.debug("转化对象成功:{}",chargingProcessDTO);
                    //1 计算电费  加另外一个微服务 计价服务
                    ChargingProcessVO chargingProcessVO = getOrderCost(chargingProcessDTO);
                    BigDecimal orderCost=new BigDecimal(0);
                    if (chargingProcessVO!=null) {
                        orderCost = chargingProcessVO.getTotalCost();
                        log.debug("查询电费结果:{}", orderCost);
                    }
                    if (chargingProcessDTO!=null){
                        //2 判断温度 大于45度 给用户推送(websocket)B级告警 大于50 推送 A级告警
                        Float temperature = chargingProcessDTO.getTemperature();
                        if (temperature > MqttTopicConstant.A_WARNING){
                            log.debug("温度超过:{} 给用户发送A级告警,实际温度:{}",MqttTopicConstant.A_WARNING,temperature);
                            WebSocketServer.sendInfo("温度过高充电失败",String.valueOf(chargingProcessDTO.getUserId()));
                        }else if (temperature > MqttTopicConstant.B_WARNING){
                            log.debug("温度超过:{} 给用户发送B级告警,实际温度:{}",MqttTopicConstant.B_WARNING,temperature);
                            WebSocketServer.sendInfo("温度较高,是否停止充电",String.valueOf(chargingProcessDTO.getUserId()));
                        }
                        //3 判断电费是否大于余额
                        BigDecimal userBalance = getUserBalance(chargingProcessDTO.getUserId());
                        if ( (userBalance.subtract(orderCost).floatValue()) <=0 ){
                            log.debug("余额不足:当前余额:{},消费金额:{}",userBalance,orderCost);
                        }
                        //4 判断是否充满

                        //5 推送(websocket)充电进度到手机端
                        syncChargingProcess2User(chargingProcessVO);
                        //6 充电进度保存 时序数据的保存
                        saveChargingProcess(chargingProcessDTO);
                    }

                }

            }

            //发送消息成功执行该方法
            @Override
            public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
                log.debug("消息接收-----------");
            }


            /**
             * 获取电费
             * @return
             */
            private ChargingProcessVO getOrderCost(ChargingProcessDTO chargingProcessDTO) {
                log.debug("准备远程调用COSTSERVICE:{}",chargingProcessDTO);
                JsonResult<ChargingProcessVO> jsonResult = costClient.getFee(chargingProcessDTO);
                if (jsonResult!=null){
                    ChargingProcessVO chargingProcessVO = jsonResult.getData();
                    if (chargingProcessVO!=null){
                        return chargingProcessVO;
                    }
                }
                return null;
            }
            /**
             * 获取用户的余额
             * @return
             */
            private BigDecimal getUserBalance(Long userId) {
                BigDecimal balance=new BigDecimal(0);
                log.debug("查询用户id为:{}的余额",userId);
                JsonResult<BigDecimal> result = userClient.getUserBalance(userId);
                if (result!=null){
                    if (StatusCode.OPERATION_SUCCESS.getCode().equals(result.getCode())){
                        balance = result.getData();
                        log.debug("当前用户余额:{}",balance);
                        return balance;
                    }
                }
                return balance;
            }

            /**
             * 给用户同步充电数据
             * @param chargingProcessVO
             */
            private void syncChargingProcess2User(ChargingProcessVO chargingProcessVO){
                log.debug("给用户同步充电进度:{}",chargingProcessVO);
            }
            /**
             * 保存充电进度数据
             * @param chargingProcessDTO
             */
            private void saveChargingProcess(ChargingProcessDTO chargingProcessDTO) {
                log.debug("传入保存充电进度数据:{}",chargingProcessDTO);
                ChargingProcessPO chargingProcessPO=new ChargingProcessPO();
                BeanUtils.copyProperties(chargingProcessDTO,chargingProcessPO);
                chargingProcessPO.setId(System.currentTimeMillis());
                chargingProcessRepository.save(chargingProcessPO);
                log.debug("保存到时序数据:{}",chargingProcessPO);
            }




        });
        //连接
        mqttClient.connect(mqttConnectOptions);
        return mqttClient;
    }
}
